using System;
using System.Runtime.InteropServices;

namespace Leap
{
	public class Image : Interface
	{
		public enum FormatType
		{
			INFRARED
		}

		private HandleRef swigCPtr;

		public byte[] Data
		{
			get
			{
				byte[] array = new byte[Width * Height * BytesPerPixel];
				DataWithArg(array);
				return array;
			}
		}

		public float[] Distortion
		{
			get
			{
				float[] array = new float[DistortionWidth * DistortionHeight];
				DistortionWithArg(array);
				return array;
			}
		}

		public long SequenceId => LeapPINVOKE.Image_SequenceId_get(swigCPtr);

		public int Id => LeapPINVOKE.Image_Id_get(swigCPtr);

		public int Width => LeapPINVOKE.Image_Width_get(swigCPtr);

		public int Height => LeapPINVOKE.Image_Height_get(swigCPtr);

		public int BytesPerPixel => LeapPINVOKE.Image_BytesPerPixel_get(swigCPtr);

		public FormatType Format => (FormatType)LeapPINVOKE.Image_Format_get(swigCPtr);

		public int DistortionWidth => LeapPINVOKE.Image_DistortionWidth_get(swigCPtr);

		public int DistortionHeight => LeapPINVOKE.Image_DistortionHeight_get(swigCPtr);

		public float RayOffsetX => LeapPINVOKE.Image_RayOffsetX_get(swigCPtr);

		public float RayOffsetY => LeapPINVOKE.Image_RayOffsetY_get(swigCPtr);

		public float RayScaleX => LeapPINVOKE.Image_RayScaleX_get(swigCPtr);

		public float RayScaleY => LeapPINVOKE.Image_RayScaleY_get(swigCPtr);

		public long Timestamp => LeapPINVOKE.Image_Timestamp_get(swigCPtr);

		public bool IsValid => LeapPINVOKE.Image_IsValid_get(swigCPtr);

		public static Image Invalid => new Image(LeapPINVOKE.Image_Invalid_get(), false);

		public Image(IntPtr cPtr, bool cMemoryOwn)
			: base(LeapPINVOKE.Image_SWIGUpcast(cPtr), cMemoryOwn)
		{
			swigCPtr = new HandleRef(this, cPtr);
		}

		public static HandleRef getCPtr(Image obj)
		{
			return obj?.swigCPtr ?? new HandleRef(null, IntPtr.Zero);
		}

		~Image()
		{
			Dispose();
		}

		public override void Dispose()
		{
			lock (this)
			{
				if (swigCPtr.Handle != IntPtr.Zero)
				{
					if (base.swigCMemOwn)
					{
						base.swigCMemOwn = false;
						LeapPINVOKE.delete_Image(swigCPtr);
					}
					swigCPtr = new HandleRef(null, IntPtr.Zero);
				}
				GC.SuppressFinalize(this);
				base.Dispose();
			}
		}

		public void DataWithArg(byte[] dst)
		{
			Marshal.Copy(DataPointer(), dst, 0, Width * Height * BytesPerPixel);
		}

		public void DistortionWithArg(float[] dst)
		{
			Marshal.Copy(DistortionPointer(), dst, 0, DistortionWidth * DistortionHeight);
		}

		public Image()
			: this(LeapPINVOKE.new_Image(), true)
		{
		}

		public IntPtr DataPointer()
		{
			return LeapPINVOKE.Image_DataPointer(swigCPtr);
		}

		public IntPtr DistortionPointer()
		{
			return LeapPINVOKE.Image_DistortionPointer(swigCPtr);
		}

		public Vector Rectify(Vector uv)
		{
			Vector result = new Vector(LeapPINVOKE.Image_Rectify(swigCPtr, Vector.getCPtr(uv)), true);
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public Vector Warp(Vector xy)
		{
			Vector result = new Vector(LeapPINVOKE.Image_Warp(swigCPtr, Vector.getCPtr(xy)), true);
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public bool Equals(Image arg0)
		{
			bool result = LeapPINVOKE.Image_Equals(swigCPtr, getCPtr(arg0));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public override string ToString()
		{
			return LeapPINVOKE.Image_ToString(swigCPtr);
		}
	}
}
